use std::sync::Arc;

use async_trait::async_trait;
use my_rust_core::{
    constants::{http_method, role},
    security::request_map_manager,
    shared::{date_helper, util},
};

use sea_orm::{DatabaseConnection, DbErr, EntityTrait, PaginatorTrait, Set};

use crate::entities;

#[async_trait]
pub trait RequestMapService: Send + Sync {
    /// Checks on request_map if it already contains data.
    /// If not the initial items will be inserted.
    async fn init(&self) -> Result<(), DbErr>;
}

pub struct RequestMapServiceImpl {
    db: Arc<DatabaseConnection>,
}

impl RequestMapServiceImpl {
    pub fn new(db: Arc<DatabaseConnection>) -> Self {
        RequestMapServiceImpl { db }
    }
}

#[async_trait]
impl RequestMapService for RequestMapServiceImpl {
    /// Checks on request_map if it already contains data.
    /// If not the initial items will be inserted.
    async fn init(&self) -> Result<(), DbErr> {
        let count = entities::prelude::RequestMap::find()
            .count(self.db.as_ref())
            .await?;

        if count == 0 {
            let models = [
                entities::request_map::ActiveModel {
                    id: Set(util::generate_uuid_as_hex_string()),
                    config_attribute: Set(String::from(
                        request_map_manager::REQUEST_MAP_PERMIT_ALL.to_owned(),
                    )),
                    http_method: Set(None),
                    url: Set(String::from("/authentication/**")),
                    date_created: Set(date_helper::get_current_naive_date_time()),
                    last_updated: Set(date_helper::get_current_naive_date_time()),
                },
                entities::request_map::ActiveModel {
                    id: Set(util::generate_uuid_as_hex_string()),
                    config_attribute: Set(String::from(
                        request_map_manager::REQUEST_MAP_PERMIT_ALL.to_owned(),
                    )),
                    http_method: Set(None),
                    url: Set(String::from("/file/**")),
                    date_created: Set(date_helper::get_current_naive_date_time()),
                    last_updated: Set(date_helper::get_current_naive_date_time()),
                },
                entities::request_map::ActiveModel {
                    id: Set(util::generate_uuid_as_hex_string()),
                    config_attribute: Set(
                        request_map_manager::REQUEST_MAP_IS_AUTHENTICATED.to_owned()
                    ),
                    http_method: Set(None),
                    url: Set(String::from("/user/**")),
                    date_created: Set(date_helper::get_current_naive_date_time()),
                    last_updated: Set(date_helper::get_current_naive_date_time()),
                },
                entities::request_map::ActiveModel {
                    id: Set(util::generate_uuid_as_hex_string()),
                    config_attribute: Set(String::from(request_map_manager::request_map_has_role(
                        role::ROLE_ACCOUNT_GROUP_ADMIN,
                    ))),
                    http_method: Set(Some(http_method::HTTP_POST.to_string())),
                    url: Set(String::from("/user/add")),
                    date_created: Set(date_helper::get_current_naive_date_time()),
                    last_updated: Set(date_helper::get_current_naive_date_time()),
                },
            ];

            entities::prelude::RequestMap::insert_many(models)
                .exec(self.db.as_ref())
                .await?;
        }

        Ok(())
    }
}
